<!DOCTYPE html>
<html>
<head>
<script src="../../../resources/js-test.js"></script>
<script src="../resources/common.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>

<script>
description("Tests importKey/deriveBits for PBKDF2");

jsTestIsAsync = true;

// -------------------------------------------------
// Successful password import and bits derivation
// -------------------------------------------------

// Test vectors were copied from:
//   https://tools.ietf.org/html/rfc6070
//

var kPbkdf2SuccessVectors = [
  {
    password: "password",
    salt: "salt",
    c: 1,
    dkLen: 20,
    hash: "SHA-1",
    derived_key: "0c60c80f961f0e71f3a9b524af6012062fe037a6"
  },

  {
    password: "password",
    salt: "salt",
    c: 2,
    dkLen: 20,
    hash: "SHA-1",
    derived_key: "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"
  },

  {
    password: "password",
    salt: "salt",
    c: 4096,
    dkLen: 20,
    hash: "SHA-1",
    derived_key: "4b007901b765489abead49d926f721d065a429c1"
  },

  {
    password: "passwordPASSWORDpassword",
    salt: "saltSALTsaltSALTsaltSALTsaltSALTsalt",
    c: 4096,
    dkLen: 25,
    hash: "SHA-1",
    derived_key: "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"
  },

  {
    password: "pass\0word",
    salt: "sa\0lt",
    c: 4096,
    dkLen: 16,
    hash: "SHA-1",
    derived_key: "56fa6aa75548099dcc37d7f03425e0c3"
  },
];

function runPbkdf2SuccessTestCase(testCase)
{
    var algorithm = {name: 'PBKDF2'};

    var key = null;
    var password = null;
    if (typeof testCase.password === 'string')
        password = asciiToUint8Array(testCase.password);
    else if (Array.isArray(testCase.password))
        password = new Uint8Array(testCase.password);

    var usages = ['deriveBits', 'deriveKey'];
    var extractable = false;

    var params = {
        name: 'PBKDF2',
        salt: asciiToUint8Array(testCase.salt),
        iterations: testCase.c,
        hash: {name: testCase.hash}
    };
    // (1) Import the password
    return crypto.subtle.importKey('raw', password, algorithm, extractable, usages).then(function(result) {
        key = result;
        // shouldBe() can only resolve variables in global context.
        tmpKey = key;
        shouldEvaluateAs("tmpKey.type", "secret");
        shouldEvaluateAs("tmpKey.extractable", false);
        shouldEvaluateAs("tmpKey.algorithm.name", "PBKDF2");
        shouldEvaluateAs("tmpKey.usages.join(',')", "deriveKey,deriveBits");

        // (2) Derive bits
        return crypto.subtle.deriveBits(params, key, testCase.dkLen*8);
    }).then(function(result) {
        bytesShouldMatchHexString("deriveBits", testCase.derived_key, result);
    });
}

var lastPromise = Promise.resolve(null);

kPbkdf2SuccessVectors.forEach(function(test) {
    lastPromise = lastPromise.then(runPbkdf2SuccessTestCase.bind(null, test));
});

lastPromise.then(finishJSTest, failAndFinishJSTest);

</script>

</body>
</html>
